<script setup lang="ts">
import { computed, reactive, ref, watch } from 'vue';
import { saveDictItem } from '@/service/api/dict';
import { useFormRules } from '@/hooks/common/form';

export interface Props {
  /** the type of operation */
  operateType: AntDesign.TableOperateType;
  /** the edit row data */
  rowData?: any;
  /** 字典类型列表 */
  dictTypes?: string[];
}

interface DictItemForm {
  dictType: string;
  itemCode: string;
  itemName: string;
  description?: string;
}

interface Emits {
  (e: 'submitted'): void;
}
const emit = defineEmits<Emits>();

const props = withDefaults(defineProps<Props>(), {
  rowData: null,
  dictTypes: () => []
});

const visible = defineModel<boolean>('open', {
  default: false
});

const formRef = ref();

function validate() {
  return formRef.value?.validate();
}

function restoreValidation() {
  formRef.value?.clearValidate();
}
const { defaultRequiredRule } = useFormRules();

const title = computed(() => {
  const titles: Record<AntDesign.TableOperateType, string> = {
    add: '新增字典项',
    edit: '编辑字典项'
  };
  return titles[props.operateType];
});

const model: DictItemForm = reactive(createDefaultModel());

function createDefaultModel(): DictItemForm {
  return {
    dictType: '',
    itemCode: '',
    itemName: '',
    description: ''
  };
}

type RuleKey = Extract<keyof DictItemForm, 'dictType' | 'itemCode' | 'itemName'>;

const rules: Record<RuleKey, App.Global.FormRule> = {
  dictType: defaultRequiredRule,
  itemCode: defaultRequiredRule,
  itemName: defaultRequiredRule
};

function handleUpdateModelWhenEdit() {
  if (props.operateType === 'add') {
    Object.assign(model, createDefaultModel());
    return;
  }

  if (props.operateType === 'edit' && props.rowData) {
    // 只复制必要属性，避免可能的循环引用
    model.dictType = props.rowData.dictType || '';
    model.itemCode = props.rowData.itemCode || '';
    model.itemName = props.rowData.itemName || '';
    model.description = props.rowData.description || '';
  }
}

async function handleSubmit() {
  await validate();

  try {
    const data = {
      ...model,
      ...(props.operateType === 'edit' && props.rowData ? { id: props.rowData.id } : {})
    };

    const { error: err } = await saveDictItem(data);
    if (!err) {
      window.$message?.success(props.operateType === 'add' ? '新增字典项成功' : '编辑字典项成功');
      closeDrawer();
      emit('submitted');
    } else {
      window.$message?.error(`操作失败：${err.message}`);
    }
  } catch (error) {
    window.$message?.error(`操作失败：${(error as any).message}`);
  }
}

function closeDrawer() {
  visible.value = false;
}

watch(visible, () => {
  if (visible.value) {
    handleUpdateModelWhenEdit();
    restoreValidation();
  }
});
</script>

<template>
  <AModal v-model:open="visible" :title="title" :width="600">
    <div class="flex-col-stretch gap-16px">
      <AForm ref="formRef" :model="model" :rules="rules" label-width="100px">
        <ARow :gutter="16">
          <ACol :span="24">
            <AFormItem label="字典类型" name="dictType">
              <ASelect v-model:value="model.dictType" placeholder="请选择或输入字典类型" show-search allow-clear>
                <ASelectOption v-for="type in props.dictTypes" :key="type" :value="type">
                  {{ type }}
                </ASelectOption>
              </ASelect>
            </AFormItem>
          </ACol>
          <ACol :span="24">
            <AFormItem label="字典编码" name="itemCode">
              <AInput v-model:value="model.itemCode" placeholder="请输入字典编码" />
            </AFormItem>
          </ACol>
          <ACol :span="24">
            <AFormItem label="映射名称" name="itemName">
              <AInput v-model:value="model.itemName" placeholder="请输入字典名称" />
            </AFormItem>
          </ACol>

          <ACol :span="24">
            <AFormItem label="描述">
              <ATextarea v-model:value="model.description" placeholder="请输入描述" :rows="3" />
            </AFormItem>
          </ACol>
        </ARow>
      </AForm>
    </div>
    <template #footer>
      <ASpace>
        <AButton @click="closeDrawer">取消</AButton>
        <AButton type="primary" @click="handleSubmit">确定</AButton>
      </ASpace>
    </template>
  </AModal>
</template>

<style scoped></style>
